# encoding: utf-8
import Config
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import Select
import re, time

from PIL import Image
from datetime import datetime
from pypinyin import lazy_pinyin, Style, pinyin
from selenium.webdriver.common.action_chains import ActionChains
import csv
import os


class Qiangpiao(object):
    def __init__(self):
        # 确定抢票车次
        self.sure_train = ''
        config = Config.Config()
        baseConfig = config.getBaseConfig(self)
        self = baseConfig
        self.driver = webdriver.Chrome()

    # 输入个人信息及车次信息
    def _inputInfo(self):
        config = Config.Config()
        inputConfig = config.getInputConfig(self)
        self = inputConfig

    # 检测车票信息输入
    def _search_infor(self, to_station = None, pinyin = None):
        # 1.跳转到查票页面
        self.driver.get(self.search_url)
        wait = WebDriverWait(self.driver, 10)

        # 判断出发地是否能被点击
        element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="fromStationText"]')))
        startAddress = self.driver.find_element(By.XPATH, '//*[@id="fromStationText"]')
        startAddress.click()
        startAddressList = self.hotAddressFind(wait)
        isFind = 0
        for address in startAddressList:
            if address.text == self.start:
                address.click()
                isFind = 1
                break
        if isFind == 0:
            startAddress.click()
            words = ''
            start_py = self.get_pinyin(self.start)
            for word in start_py.split(','):
                words = words + word
            startAddress.send_keys(words)
        time.sleep(1)
        isFind = self.isHavePage(wait, isFind, self.start)
        if isFind == 0:
            print('出发地输入错误')
            return False
        
        # 判断目的地能否被点击
        element = wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="toStationText"]')))
        toStationAddress = self.driver.find_element(By.XPATH, '//*[@id="toStationText"]')
        toStationAddress.click()
        toStationAddressList = self.hotAddressFind(wait)
        isFind = 0
        for address in toStationAddressList:
            if address.text == str(to_station or self.to_station):
                address.click()
                isFind = 1
                break
        if isFind == 0:
            toStationAddress.click()
            words = ''
            to_station_py = self.get_pinyin(self.to_station)
            for word in str(pinyin or to_station_py).split(','):
                words = words + word
            toStationAddress.send_keys(words)
        time.sleep(1)
        isFind = self.isHavePage(wait, isFind, str(to_station or self.to_station))
        if isFind == 0:
            print('目的地输入错误')
            return False
        
        # 时间
        toStationAddress = self.driver.find_element(By.ID, 'train_date')
        toStationAddress.clear()
        print(self.start_time)
        toStationAddress.send_keys(self.start_time)
        
        # 2.等待出发地是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'fromStationText'), self.start)
        )
        # 3.等待目的地是否输入正确
        WebDriverWait(self.driver, 1000).until(
            EC.text_to_be_present_in_element_value((By.ID, 'toStationText'), str(to_station or self.to_station))
        )
        # 4.等待出发日期是否输入正确
        WebDriverWait(self.driver, 1000).until(
            
            EC.text_to_be_present_in_element_value((By.ID, 'train_date'), self.start_time)
        )
        # 5.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 1000).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )

    def cityFind(self, wait, isFind, address):
        formCities = wait.until(EC.presence_of_element_located((By.ID, 'form_cities')))
        formList = self.driver.find_elements(By.XPATH, '//*[@id="panel_cities"]/div')
        for city in formList:
            if city.find_element(By.CLASS_NAME, 'ralign').text == address:
                city.click()
                isFind = 1
                break
        return isFind
    def isHavePage(self, wait, isFind, address):
        over = 1
        while over:
            isFind = self.cityFind(wait, isFind, address)
            time.sleep(1)
            if isFind == 0:
                # 判断是否有分页
                page = self.driver.find_element(By.ID, "flip_cities")
                if page.is_displayed():
                    
                    pageChange    = page.find_elements(By.CLASS_NAME, 'pagetxt')
                    curFooterLink = page.find_element(By.CLASS_NAME, 'cur')
                    number = 0
                    for change in pageChange:
                        if number == 0:
                            if curFooterLink and curFooterLink.text == '1':
                                change.click()
                                break
                            if len(pageChange) == 1:
                                over = 0
                            number = number + 1
                            continue
                        else:
                            change.click()
                            break
                else:
                    break
            else:
                break
        return isFind
    def hotAddressFind(self, wait):
        wait.until(EC.presence_of_element_located((By.ID, 'panel_cities2')))
        # 目的地热门地址
        hot = self.driver.find_element(By.XPATH, '//*[@id="panel_cities2"]/div[1]/div[1]')
        hot.click()
        wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="ul_list1"]/li')))

        startAddressList = self.driver.find_elements(By.XPATH, '//*[@id="ul_list1"]/li')
        return startAddressList

    def _click_search(self):
        # 1.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )
        # 点击查询按钮
        queryBtn = self.driver.find_element(By.ID, 'query_ticket')
        queryBtn.click()

        # 等待查询页面有数据显示    
        wait = WebDriverWait(self.driver, 10)
        element = wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
        trDom  = self.driver.find_elements(By.XPATH, '//*[@id="queryLeftTable"]/tr')
        
        tr_list = self.driver.find_elements(By.XPATH, '//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
        tr_array = []
        for tr in tr_list:
            if tr.is_displayed():
                result = self.getCourse(tr)
                if result:
                    tr_array.append(result)
            else:
                print('已拿到所有过程站')
                continue
        # 未检测到符合条件的车票
        i = 0
        names = []
        for tr in tr_array:
            if i % 2 == 0:
                result = self.grt_numbers(tr)
                start_time = tr.find_element(By.CLASS_NAME,'start-t').text
                car_number = tr.find_element(By.CLASS_NAME,'number').text
                names.append({'number':car_number, 'name':result, 'time':start_time})
            i = i + 1
        i = 0
        for tr in tr_array:
            if i % 2 != 0:
                result = self.grt_numbers(tr)
                start_time = tr.find_element(By.CLASS_NAME,'start-t').text
                car_number = tr.find_element(By.CLASS_NAME,'number').text
                names.append({'number':car_number, 'name':result, 'time':start_time})
            i = i + 1
        self.write_csv(names)

        name_array = []
        array = {}

        for name in names:
            nameArray = tuple(name['name'])  # 将列表转换为元组
            for nameAlone in nameArray:
                if nameAlone in name_array:
                    array[nameAlone].append(name['number'])
                else:
                    name_array.append(nameAlone)
                    array.setdefault(nameAlone, []).append(name['number'])
        # 查询有车票的车次
        self.find_train(array)

        print('查询完毕')

        return False
    def find_train(self, train):
        self.driver.get(self.search_url)
        result = []
        print(train)
        for key in train.keys():
            print(key)
            if key:
                pinyin = self.get_pinyin(key)
                print(pinyin, key)
                self._search_infor(key, pinyin)
                res = self._click_search_for_train(train[key])
                if res:
                    result.append({'result':res, 'name':key})
        self.write_csv(result, True)
    
    def write_csv(self, names, train = None):
        if train:
            with open('trains.csv', mode='a', newline='', encoding='utf-8') as file:
                fieldnames = ['status', 'price', 'seat', 'number', 'time', 'name']

                data = []
                for name in names:
                    if name:
                        for na in name['result']:
                            data.append({'status':na['status'], 'price':na['price'], 'seat':na['seat'], 'number':na['number'], 'time':na['time'], 'name':name['name']})

                writer = csv.DictWriter(file, fieldnames=fieldnames)
                if os.stat('trains.csv').st_size == 0:
                    writer.writeheader()
                writer.writerows(data)
            print("符合条件的车次CSV文件写入成功！")
            
        else :
            with open('name.csv', mode='w', newline='', encoding='utf-8') as file:
                fieldnames = ['number', 'name', 'time']
                writer = csv.DictWriter(file, fieldnames=fieldnames)
                # 写入表头
                writer.writeheader()
                # 写入数据
                writer.writerows(names)
            print("所有路过站点CSV文件写入成功！")

    def _click_search_for_train(self, number):

        print('点击了查询')
        # 1.查看查询按钮是否可以被点击
        WebDriverWait(self.driver, 10).until(
            EC.element_to_be_clickable((By.ID, 'query_ticket'))
        )
        # 点击查询按钮
        queryBtn = self.driver.find_element(By.ID, 'query_ticket')
        queryBtn.click()

        # 等待查询页面有数据显示    
        wait = WebDriverWait(self.driver, 10)
        wait.until(EC.presence_of_element_located((By.XPATH, '//*[@id="queryLeftTable"]/tr')))
        tr_list = self.driver.find_elements(By.XPATH, '//tbody[@id="queryLeftTable"]/tr[not(@datatran)]')
        for tr in tr_list:
            print('tr检索中')
            if tr.is_displayed():
                train_number = tr.find_element(By.CLASS_NAME, 'number').text
                if train_number in number:
                    tickets = tr.find_elements(By.XPATH, './/td')
                    i = 0
                    td_status = []
                    is_click = 0
                    for ticket in tickets:
                        if i == 0:
                            i = i + 1
                            continue
                        i = i + 1
                        status = ticket.text
                        if status == '有' or status.isdigit():
                            time.sleep(1)
                            if is_click == 0:
                                ticket.click()
                                is_click = 1
                            time.sleep(1)
                            datatran = train_number
                            xpath = f"//tr[@datatran='{datatran}']/td[{i}]"
                            dom = self.driver.find_element(By.XPATH, xpath)
                            print('价格')
                            price = dom.text
                            time.sleep(1)
                            print(price)
                            self.sure_train = train_number
                            seat = self.seatZH[i]
                            start_time = tr.find_element(By.CLASS_NAME,'start-t').text
                            td_status.append({'status':status, 'price':price, 'seat':seat, 'number':train_number, 'time':start_time})
                    return td_status
            else:
                return False
        return False

    def getCourse(self, tr):
        web_time_start = tr.find_element(By.CLASS_NAME, 'start-t').text
        web_time_start = datetime.strptime(web_time_start, "%H:%M")
        start_time = datetime.strptime(self.start_time_limit, "%H:%M")
        end_time = datetime.strptime(self.end_time_limit, "%H:%M")
        if start_time > web_time_start or end_time < web_time_start:
            return False
        else:
            return tr

    def grt_numbers(self, tr):
        number = tr.find_element(By.CLASS_NAME, 'number')
        wait = WebDriverWait(self.driver, 10)
        wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'number')))
        wait.until(
            EC.element_to_be_clickable((By.CLASS_NAME, 'number'))
        )
        # 滚动到元素
        actions = ActionChains(self.driver)
        actions.move_to_element(number).perform()
        number.click()
        time.sleep(1)
        wait.until(
            EC.presence_of_element_located((By.XPATH, '//*[@id="train_table_"]/tr'))
        )
        train_list = tr.find_elements(By.XPATH, '//*[@id="train_table_"]/tr')

        i = 0
        train_name_array = []
        for train in train_list:
            train_name = train.find_element(By.XPATH, './td[2]').text
            if i == 0 and train_name != self.start:
                continue
            if train_name == self.start:
                i = 1
                continue
            elif train_name == self.to_station:
                break
            else :
                train_name_array.append(train_name)
        return train_name_array

    def get_pinyin(self, train):
        # 获取拼音首字母
        pinyin_initials = lazy_pinyin(train)

        # 将拼音首字母连接成字符串
        pinyin_initials_str = ",".join(pinyin_initials)

        # 输出结果
        return pinyin_initials_str


    # 检查元素是存在：
    def isElementExits(self, xpath):
        s = self.driver.find_elements(By.XPATH, xpath)
        if len(s) == 0:
            return False
        else:
            return True

    def run(self):
        self._search_infor()
        self._click_search()

if __name__ == '__main__':
    spider = Qiangpiao()
    spider._inputInfo()
    spider.run()
